<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { ElMessage, type TableColumnCtx } from 'element-plus'
import RechangeDialog from './RechangeDialog.vue'
import CalorieChart from './CalorieChart.vue'
import NutritionChart from './NutritionChart.vue'
import DurationChart from './DurationChart.vue'
import { useRouter } from 'vue-router'
import debounce from 'lodash/debounce'
import dayjs from 'dayjs'
import type { FoodI, FoodPlanI } from '@/types/food'
import { getFoodPlanListUtil, updateSingleFoodPlanUtil } from '@/AGC/utils/food_plan'
import { useUserStore } from '@/stores/user'
import { getFoodListByFoodPlanUtil } from '@/AGC/utils/food'
import { createExerciseDislikeUtil, createFoodDislikeUtil } from '@/AGC/utils/dislike'
import type { ExerciseI, ExercisePlanI } from '@/types/exercise'
import { getExercisePlanListUtil, updateSingleExercisePlanUtil } from '@/AGC/utils/exercise_plan'
import { getExerciseListByPlanUtil } from '@/AGC/utils/exercise'
import { getTotalCalories } from '@/utils'
import { usePlanStore } from '@/stores/plan'
import { showDialog } from 'vant'

const store = usePlanStore()
// 表格合并单元格参数
interface SpanMethodProps {
  row: FoodPlanI
  column: TableColumnCtx<FoodPlanI>
  rowIndex: number
  columnIndex: number
}
const router = useRouter()
const scrollContainer = ref<HTMLElement | null>(null)
// 滚动距离
const scrollY = ref(0)
// 监听滚动事件
const handleScroll = debounce(() => {
  scrollY.value = scrollContainer.value?.scrollTop || 0
  sessionStorage.setItem('scrollY', scrollY.value.toString())
}, 100)
// 组件挂载
onMounted(() => {
  // 从 sessionStorage 中读取之前保存的滚动距离
  const savedScrollY = sessionStorage.getItem('scrollY') || '0'
  scrollY.value = parseInt(savedScrollY)
  scrollContainer.value?.scrollTo(0, scrollY.value)
})
// 筛选计划表
const tableName = ref('food')
// 筛选周期
const dateString = ref(dayjs().format('YYYY-MM-DD'))
// 获取饮食计划列表
const foodPlanList = ref<FoodPlanI[]>([])
const getFoodPlanList = async () => {
  try {
    foodPlanList.value = await getFoodPlanListUtil(dateString.value)
    const totalCalories = getTotalCalories(foodPlanList.value)
    store.setRecIngestion(totalCalories)
  } catch (error) {
    ElMessage.error('饮食计划列表获取失败，请稍后再试')
    Promise.reject(error)
  }
}
// 获取运动计划列表
const exercisePlanList = ref<ExercisePlanI[]>([])
const getExercisePlanList = async () => {
  try {
    exercisePlanList.value = await getExercisePlanListUtil(dateString.value)
    const totalCalories = getTotalCalories(exercisePlanList.value)
    store.setRecConsume(totalCalories)
  } catch (error) {
    ElMessage.error('运动计划列表获取失败，请稍后再试')
    Promise.reject(error)
  }
}
// 监听日期变化
watch(
  dateString,
  async (value) => {
    if (value) {
      setTimeout(async () => {
        await getFoodPlanList()
        await getExercisePlanList()
        store.setDate(value)
      }, 100)
    }
  },
  { immediate: true },
)
// 合并饮食计划表
const foodSpanMethod = (spanMethodProps: SpanMethodProps) => {
  if (spanMethodProps.columnIndex === 0) {
    if (spanMethodProps.rowIndex % 3 === 0) {
      return {
        rowspan: 3,
        colspan: 1,
      }
    } else {
      return {
        rowspan: 0,
        colspan: 0,
      }
    }
  }
}
// 换个口味弹窗显隐
const changeOneDialog = ref(false)
// 禁用日期
const disabledDate = (time: Date) => {
  const today = dayjs(useUserStore().userFilter?.date)
  return time.getTime() < today.valueOf()
}
// 食物 | 训练项目 名称
const names = ref<string[]>([])
// 食物 | 训练项目 列表
const list = ref<FoodI[] | ExerciseI[]>([])
// 用户选择的计划
const choosePlan = ref<FoodPlanI | ExercisePlanI>()
// 换个口味 | 换个运动 标题
const title = ref('')
// 换个口味 | 换个运动 点击事件
const changeOneOnClick = async (row: FoodPlanI | ExercisePlanI, dislike: number) => {
  // 保存用户选择的计划
  choosePlan.value = row

  try {
    if (tableName.value == 'food') {
      row = row as FoodPlanI
      // 设置标题
      title.value = row.food_name + ' — 换个口味'
      // 创建用户已不喜欢的食物
      if (dislike) await createFoodDislikeUtil(row.food_name)
      // 获取过滤后的食物计划列表 和 食物名称列表
      list.value = await getFoodListByFoodPlanUtil(row)
      names.value = list.value.map((item) => item.name)
    } else {
      row = row as ExercisePlanI
      // 设置标题
      title.value = row.exercise_name + ' — 换个运动'
      // 创建用户已不喜欢的运动
      if (dislike) await createExerciseDislikeUtil(row.exercise_name)
      // 获取过滤后的运动计划列表 和 运动名称列表
      list.value = await getExerciseListByPlanUtil(row)
      names.value = list.value.map((item) => item.name)
    }

    changeOneDialog.value = true
  } catch (error) {
    ElMessage.error('获取失败, 请稍后再试')
    Promise.reject(error)
  }
}
// 用户选择完成后的触发事件
const success = async (name: string) => {
  // 筛选出用户的选择
  const chooseItem = list.value.find((item) => item.name == name)
  try {
    if (tableName.value == 'food') {
      // 更新单个饮食计划
      await updateSingleFoodPlanUtil(chooseItem as FoodI, choosePlan.value as FoodPlanI)
      // 获取更新后的饮食计划列表
      await getFoodPlanList()
      ElMessage.success('口味选择成功')
    } else {
      // 更新单个运动计划
      await updateSingleExercisePlanUtil(chooseItem as ExerciseI, choosePlan.value as ExercisePlanI)
      // 获取更新后的运动计划列表
      await getExercisePlanList()
      ElMessage.success('运动选择成功')
    }
  } catch (error) {
    ElMessage.error('更新失败，请稍后再试')
    Promise.reject(error)
  }
}
// 子组件去收集点击事件
const goCollect = async () => {
  const currentDate = new Date(dayjs().format('YYYY-MM-DD'))
  const chooseDate = new Date(dateString.value)

  if (chooseDate < currentDate) {
    await showDialog({
      title: '温馨提示',
      message: '时间已经过去了, 好可惜呀',
      theme: 'round-button',
    })
  } else if (chooseDate > currentDate) {
    await showDialog({
      title: '温馨提示',
      message: '不要心急哦~, 时间还没到呢',
      theme: 'round-button',
    })
  } else {
    router.push({
      path: '/record',
    })
  }
}
</script>

<template>
  <div class="page-container" @scrollend="handleScroll" ref="scrollContainer">
    <!-- 计划卡片 -->
    <el-card>
      <template #header>
        <div class="card-header">
          <!-- 筛选条件 -->
          <el-radio-group v-model="tableName">
            <el-radio value="food" size="large">饮食计划表</el-radio>
            <el-radio value="exercise" size="large">健身计划表</el-radio>
          </el-radio-group>
          <span>{{ tableName == 'food' ? '饮食计划表' : '健身计划表' }}</span>
          <el-date-picker
            v-model="dateString"
            type="date"
            placeholder="选择日期"
            size="large"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            :disabled-date="disabledDate"
          />
        </div>
      </template>
      <!-- 饮食计划表 -->
      <el-table
        v-if="tableName == 'food'"
        :data="foodPlanList"
        :span-method="foodSpanMethod"
        border
      >
        <el-table-column label="时间段" prop="time" align="center"></el-table-column>
        <el-table-column label="食物名称" prop="food_name" align="center"></el-table-column>
        <el-table-column label="份量" prop="weight" align="center">
          <template #default="{ row }">{{ row.weight + ' ' + row.unit }}</template>
        </el-table-column>
        <el-table-column label="热量(千卡)" prop="calories" align="center"></el-table-column>
        <el-table-column label="主要营养成分" prop="nutrition" align="center"></el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="{ row }">
            <el-popconfirm
              width="220"
              title="是因为不喜欢这个食物吗"
              @cancel="changeOneOnClick(row, 0)"
              @confirm="changeOneOnClick(row, 1)"
            >
              <template #reference>
                <el-button type="text">换个口味</el-button>
              </template>
              <template #actions="{ confirm, cancel }">
                <div style="display: flex; justify-content: space-evenly">
                  <el-button size="small" @click="cancel">不是</el-button>
                  <el-button type="danger" size="small" @click="confirm"> 是的 </el-button>
                </div>
              </template>
            </el-popconfirm>
            <!-- <el-button type="text" @click="changeOneOnClick(row)">换个口味</el-button> -->
          </template>
        </el-table-column>
      </el-table>
      <!-- 健身计划表 -->
      <el-table v-else :data="exercisePlanList" border>
        <el-table-column label="训练项目" align="center" prop="exercise_name"></el-table-column>
        <el-table-column label="训练量" align="center" prop="amount">
          <template #default="{ row }">{{ row.amount + ' ' + row.unit }}</template>
        </el-table-column>
        <el-table-column label="消耗热量(千卡)" align="center" prop="calories"></el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="{ row }">
            <el-popconfirm
              width="220"
              title="是因为不喜欢这个运动吗"
              @cancel="changeOneOnClick(row, 0)"
              @confirm="changeOneOnClick(row, 1)"
            >
              <template #reference>
                <el-button type="text">换个运动</el-button>
              </template>
              <template #actions="{ confirm, cancel }">
                <div style="display: flex; justify-content: space-evenly">
                  <el-button size="small" @click="cancel">不是</el-button>
                  <el-button type="danger" size="small" @click="confirm"> 是的 </el-button>
                </div>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- 图表 -->
    <div style="display: flex; justify-content: space-between; flex-wrap: wrap; width: 100%">
      <!-- 每日能量 -->
      <CalorieChart @goCollect="goCollect"></CalorieChart>
      <!-- 营养成分 -->
      <NutritionChart @goCollect="goCollect"></NutritionChart>
      <!-- 训练量 -->
      <DurationChart @goCollect="goCollect"></DurationChart>
    </div>
    <!-- 弹窗 -->
    <RechangeDialog
      v-model="changeOneDialog"
      :names="names"
      @success="success"
      :title="title"
    ></RechangeDialog>
  </div>
</template>

<style scoped lang="less">
.page-container {
  width: 100%;
  overflow-y: auto; /* 启用垂直滚动 */
  height: 100%;
  box-sizing: border-box; /* 确保内边距和边框不会增加元素的总宽度和高度 */
  padding: 20px;

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px; /* 添加内边距 */
    box-sizing: border-box; /* 确保内边距不会增加元素的总宽度和高度 */
  }

  .el-card {
    margin: 10px; /* 添加外边距 */
    box-sizing: border-box; /* 确保外边距不会增加元素的总宽度和高度 */
  }

  .el-table {
    box-sizing: border-box; /* 确保内边距不会增加元素的总宽度和高度 */

    ::v-deep(.el-table__header th) {
      background-color: rgb(237, 237, 237, 0.9);
      color: rgb(43, 37, 37);
      padding: 10px 0;
    }

    ::v-deep(.el-table__body tr) {
      height: 50px;
    }
  }
}
</style>
